package com.evil.account.config;

import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.context.request.WebRequest;

import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Map;

/**
 * @author liyang
 * @date 2023-02-03 15:22
 */
@Component
public class DefineErrorAttributes extends DefaultErrorAttributes {

    private static final String CODE = "code";
    private static final String DATA = "data";
    private static final String TRACE = "trace";
    private static final String MESSAGE = "message";

    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
        Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, options);
        errorAttributes.put(DATA, null);
        errorAttributes.put(TRACE, null);
        Throwable error = this.getError(webRequest);
        // 自定义业务异常
        if (error instanceof BusinessException) {
            BusinessException e = (BusinessException) error;
            errorAttributes.put(CODE, e.getCode());
            errorAttributes.put(DATA, e.getData());
            errorAttributes.put(MESSAGE, e.getMessage());
        }
        // 方法参数异常
        else if (error instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException e = (MethodArgumentNotValidException) error;
            List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
            String errorMessage = fieldErrors.get(0).getDefaultMessage();
            errorAttributes.put(CODE, RCodeEnum.ERROR_RUNTIME.getCode());
            errorAttributes.put(MESSAGE, errorMessage);
        }
        // 约束冲突
        else if (error instanceof ConstraintViolationException) {
            ConstraintViolationException e = (ConstraintViolationException) error;
            errorAttributes.put(CODE, RCodeEnum.ERROR_RUNTIME.getCode());
            errorAttributes.put(MESSAGE, e.getMessage());
        }
        // bind
        else if (error instanceof BindException) {
            BindException e = (BindException) error;
            List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
            String errorMessage = fieldErrors.get(0).getDefaultMessage();
            errorAttributes.put(CODE, RCodeEnum.ERROR_RUNTIME.getCode());
            errorAttributes.put(MESSAGE, errorMessage);
        }
        // 运行时异常 || 系统异常
        else if (error instanceof Exception) {
            errorAttributes.put(CODE, RCodeEnum.ERROR_RUNTIME.getCode());
            errorAttributes.put(MESSAGE, StringUtils.defaultIfBlank(error.getMessage(), RCodeEnum.ERROR_RUNTIME.getMessage()));
        }
        // 系统异常
        else {
            errorAttributes.put(CODE, RCodeEnum.ERROR_RUNTIME.getCode());
            errorAttributes.put(MESSAGE, RCodeEnum.ERROR_RUNTIME.getMessage());
        }
        return errorAttributes;
    }
}
